import gradio as gr
import requests
import pandas as pd
from typing import List, Dict, Any
import os
from PIL import Image
from datetime import datetime, timedelta
import matplotlib.pyplot as plt
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import seaborn as sns
from collections import defaultdict, Counter
import json

# 动态配置API基础URL
def get_api_base_url():
    """获取API基础URL，支持配置文件和环境变量"""
    # 1. 优先使用环境变量
    env_url = os.environ.get('API_BASE_URL')
    if env_url:
        return env_url

    # 2. 尝试读取配置文件
    try:
        config_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "config.json")
        if os.path.exists(config_path):
            with open(config_path, 'r', encoding='utf-8') as f:
                config = json.load(f)
                return config.get('api_base_url', 'http://127.0.0.1:8000/api/v1')
    except Exception as e:
        print(f"读取配置文件失败: {e}")

    # 3. 默认使用localhost
    return "http://127.0.0.1:8000/api/v1"

# 配置
API_BASE_URL = get_api_base_url()
print(f"使用API基础URL: {API_BASE_URL}")

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False


def test_api_connection():
    """测试API连接"""
    # 优先使用localhost进行连接测试
    test_urls = [
        "http://127.0.0.1:8000/",
        API_BASE_URL.replace('/api/v1', '') + "/"
    ]

    for url in test_urls:
        try:
            print(f"🔄 测试连接: {url}")
            response = requests.get(url, timeout=10)
            if response.status_code == 200:
                print(f"✅ API连接成功: {url}")
                return True
        except Exception as e:
            print(f"❌ {url} 连接失败: {e}")

    print(f"❌ 所有API连接测试失败")
    return False


def get_formulas() -> pd.DataFrame:
    """从API获取所有公式并返回DataFrame"""
    try:
        response = requests.get(f"{API_BASE_URL}/admin/formulas", timeout=10)
        if response.status_code == 200:
            formulas = response.json()
            if formulas:
                df = pd.DataFrame(formulas)
                # 重命名列为中文
                df = df.rename(columns={
                    'id': 'ID',
                    'latex': 'LaTeX公式',
                    'created_at': '创建时间'
                })
                # 转换时间格式
                if '创建时间' in df.columns:
                    df['创建时间'] = pd.to_datetime(df['创建时间']).dt.strftime('%Y-%m-%d %H:%M:%S')

                # 添加操作列
                df['操作'] = df['ID'].apply(lambda x: f"移除")

                # 重新排列列顺序
                df = df[['ID', 'LaTeX公式', '创建时间', '操作']]
                return df
            else:
                return pd.DataFrame(columns=['ID', 'LaTeX公式', '创建时间', '操作'])
        else:
            print(f"获取公式失败，状态码: {response.status_code}")
            return pd.DataFrame(columns=['ID', 'LaTeX公式', '创建时间', '操作'])
    except requests.exceptions.ConnectionError as e:
        print(f"网络连接错误: {e}")
        print(f"请检查API服务器是否运行在: {API_BASE_URL}")
        return pd.DataFrame(columns=['ID', 'LaTeX公式', '创建时间', '操作'])
    except requests.exceptions.Timeout as e:
        print(f"请求超时: {e}")
        return pd.DataFrame(columns=['ID', 'LaTeX公式', '创建时间', '操作'])
    except Exception as e:
        print(f"获取公式时出错: {e}")
        return pd.DataFrame(columns=['ID', 'LaTeX公式', '创建时间', '操作'])


def get_formula_choices():
    """获取所有公式选项用于筛选下拉框"""
    try:
        response = requests.get(f"{API_BASE_URL}/admin/formulas")
        if response.status_code == 200:
            formulas = response.json()
            choices = [("全部公式", None)]  # 添加"全部"选项
            for formula in formulas:
                # 截断过长的LaTeX公式以便显示
                latex_display = formula['latex']
                if len(latex_display) > 50:
                    latex_display = latex_display[:47] + "..."
                choices.append((f"ID{formula['id']}: {latex_display}", formula['id']))
            return choices
        else:
            return [("全部公式", None)]
    except Exception as e:
        print(f"Error fetching formulas: {e}")
        return [("全部公式", None)]


def get_submissions(skip: int = 0, limit: int = 100, formula_id: int = None, status: str = None) -> pd.DataFrame:
    """从API获取提交记录并返回DataFrame"""
    try:
        # 构建查询参数
        params = {"skip": skip, "limit": limit}
        if formula_id is not None:
            params["formula_id"] = formula_id
        if status is not None and status != "全部状态":
            params["status"] = status

        response = requests.get(f"{API_BASE_URL}/admin/submissions", params=params)
        if response.status_code == 200:
            data = response.json()
            submissions = data.get('submissions', [])
            if submissions:
                # 扁平化数据用于显示
                flattened = []
                for sub in submissions:
                    # 状态中文化
                    status_map = {
                        'pending': '待处理',
                        'processing': '处理中',
                        'completed': '已完成',
                        'failed': '失败'
                    }
                    # 生成图片URL
                    image_url = ""
                    if sub['image_path']:
                        # 将本地路径转换为HTTP URL
                        image_filename = os.path.basename(sub['image_path'])
                        image_url = f"http://127.0.0.1:8000/uploads/{image_filename}"

                    flat_sub = {
                        '公式ID': sub['formula_id'],
                        '公式内容': sub['formula']['latex'] if sub.get('formula') else '无',
                        '状态': status_map.get(sub['status'], sub['status']),
                        'OCR结果': sub.get('ocr_result', '无'),
                        '创建时间': sub['created_at']
                    }
                    flattened.append(flat_sub)

                df = pd.DataFrame(flattened)
                # 转换时间格式
                if '创建时间' in df.columns:
                    df['创建时间'] = pd.to_datetime(df['创建时间']).dt.strftime('%Y-%m-%d %H:%M:%S')
                return df
            else:
                return pd.DataFrame(columns=['公式ID', '公式内容', '状态', 'OCR结果', '创建时间'])
        else:
            return pd.DataFrame(columns=['公式ID', '公式内容', '状态', 'OCR结果', '创建时间'])
    except Exception as e:
        print(f"获取提交记录时出错: {e}")
        return pd.DataFrame(columns=['公式ID', '公式内容', '状态', 'OCR结果', '创建时间'])


def get_statistics() -> Dict[str, Any]:
    """获取统计数据"""
    try:
        # 获取公式统计
        formulas_response = requests.get(f"{API_BASE_URL}/admin/formulas")
        formulas_count = len(formulas_response.json()) if formulas_response.status_code == 200 else 0

        # 获取提交统计
        submissions_response = requests.get(f"{API_BASE_URL}/admin/submissions?limit=1000")
        if submissions_response.status_code == 200:
            submissions_data = submissions_response.json()
            total_submissions = submissions_data.get('total', 0)
            submissions = submissions_data.get('submissions', [])

            # 今日提交数
            today = datetime.now().date()
            today_submissions = 0
            status_counts = {'待处理': 0, '处理中': 0, '已完成': 0, '失败': 0}

            for sub in submissions:
                # 统计今日提交
                created_date = datetime.fromisoformat(sub['created_at'].replace('Z', '+00:00')).date()
                if created_date == today:
                    today_submissions += 1

                # 统计状态分布
                status_map = {
                    'pending': '待处理',
                    'processing': '处理中',
                    'completed': '已完成',
                    'failed': '失败'
                }
                status_cn = status_map.get(sub['status'], '其他')
                if status_cn in status_counts:
                    status_counts[status_cn] += 1
        else:
            total_submissions = 0
            today_submissions = 0
            status_counts = {'待处理': 0, '处理中': 0, '已完成': 0, '失败': 0}

        return {
            'formulas_count': formulas_count,
            'total_submissions': total_submissions,
            'today_submissions': today_submissions,
            'status_counts': status_counts
        }
    except Exception as e:
        print(f"获取统计数据时出错: {e}")
        return {
            'formulas_count': 0,
            'total_submissions': 0,
            'today_submissions': 0,
            'status_counts': {'待处理': 0, '处理中': 0, '已完成': 0, '失败': 0}
        }


def create_submission_trend_chart():
    """创建提交趋势图表"""
    try:
        # 获取提交数据
        response = requests.get(f"{API_BASE_URL}/admin/submissions?limit=1000", timeout=10)
        if response.status_code != 200:
            print(f"获取提交数据失败，状态码: {response.status_code}")
            return None

        submissions_data = response.json()
        submissions = submissions_data.get('submissions', [])

        if not submissions:
            print("没有提交数据，无法创建趋势图")
            return None

        # 按日期统计提交数量
        daily_counts = defaultdict(int)
        for sub in submissions:
            created_date = datetime.fromisoformat(sub['created_at'].replace('Z', '+00:00')).date()
            daily_counts[created_date] += 1

        # 生成最近7天的数据
        today = datetime.now().date()
        dates = [today - timedelta(days=i) for i in range(6, -1, -1)]
        counts = [daily_counts.get(date, 0) for date in dates]
        date_labels = [date.strftime('%m-%d') for date in dates]

        # 创建Plotly图表
        fig = go.Figure()
        fig.add_trace(go.Scatter(
            x=date_labels,
            y=counts,
            mode='lines+markers',
            name='每日提交数',
            line=dict(color='#1f77b4', width=3),
            marker=dict(size=8)
        ))

        fig.update_layout(
            title='📈 最近7天提交趋势',
            xaxis_title='日期',
            yaxis_title='提交数量',
            font=dict(size=12),
            height=400,
            showlegend=False
        )

        return fig

    except requests.RequestException as e:
        print(f"网络请求错误: {e}")
        return None
    except Exception as e:
        print(f"创建趋势图表时出错: {e}")
        import traceback
        traceback.print_exc()
        return None


def create_formula_popularity_chart():
    """创建公式热度排行图表"""
    try:
        # 获取提交数据
        response = requests.get(f"{API_BASE_URL}/admin/submissions?limit=1000", timeout=10)
        if response.status_code != 200:
            print(f"获取提交数据失败，状态码: {response.status_code}")
            return None

        submissions_data = response.json()
        submissions = submissions_data.get('submissions', [])

        if not submissions:
            print("没有提交数据，无法创建热度图")
            return None

        # 统计每个公式的提交次数
        formula_counts = Counter()
        formula_names = {}

        for sub in submissions:
            formula_id = sub['formula_id']
            formula_latex = sub['formula']['latex'] if sub.get('formula') else f'公式{formula_id}'
            formula_counts[formula_id] += 1
            formula_names[formula_id] = formula_latex

        # 获取前10个最热门的公式
        top_formulas = formula_counts.most_common(10)

        if not top_formulas:
            return None

        # 准备数据
        formula_labels = []
        counts = []

        for formula_id, count in top_formulas:
            latex = formula_names.get(formula_id, f'公式{formula_id}')
            # 截断过长的LaTeX公式
            if len(latex) > 30:
                latex = latex[:27] + '...'
            formula_labels.append(f'ID{formula_id}: {latex}')
            counts.append(count)

        # 创建水平条形图
        fig = go.Figure()
        fig.add_trace(go.Bar(
            x=counts,
            y=formula_labels,
            orientation='h',
            marker=dict(color='#ff7f0e')
        ))

        fig.update_layout(
            title='🔥 公式热度排行榜 (Top 10)',
            xaxis_title='提交次数',
            yaxis_title='公式',
            font=dict(size=12),
            height=500,
            showlegend=False
        )

        return fig

    except requests.RequestException as e:
        print(f"网络请求错误: {e}")
        return None
    except Exception as e:
        print(f"创建公式热度图表时出错: {e}")
        import traceback
        traceback.print_exc()
        return None


def create_status_pie_chart():
    """创建状态分布饼图"""
    try:
        stats = get_statistics()
        status_counts = stats['status_counts']

        # 过滤掉数量为0的状态
        filtered_counts = {k: v for k, v in status_counts.items() if v > 0}

        if not filtered_counts:
            return None

        labels = list(filtered_counts.keys())
        values = list(filtered_counts.values())

        # 定义颜色
        colors = ['#ff9999', '#66b3ff', '#99ff99', '#ffcc99']

        fig = go.Figure(data=[go.Pie(
            labels=labels,
            values=values,
            hole=0.3,
            marker=dict(colors=colors[:len(labels)])
        )])

        fig.update_layout(
            title='📊 提交状态分布',
            font=dict(size=12),
            height=400,
            showlegend=True
        )

        return fig

    except Exception as e:
        print(f"创建状态饼图时出错: {e}")
        import traceback
        traceback.print_exc()
        return None


def create_formula(latex: str) -> str:
    """创建新公式"""
    if not latex.strip():
        return "错误：LaTeX公式不能为空"

    try:
        response = requests.post(f"{API_BASE_URL}/admin/formulas", json={"latex": latex})
        if response.status_code == 200:
            return f"公式创建成功：{latex}"
        else:
            return f"创建公式时出错：{response.text}"
    except Exception as e:
        return f"创建公式时出错：{e}"


def delete_formula(formula_id: int) -> str:
    """根据ID删除公式"""
    if not formula_id:
        return "❌ 错误：请提供有效的公式ID"

    try:
        # 先获取公式信息用于确认
        get_response = requests.get(f"{API_BASE_URL}/admin/formulas")
        target_formula = None
        if get_response.status_code == 200:
            formulas = get_response.json()
            for formula in formulas:
                if formula['id'] == formula_id:
                    target_formula = formula
                    break

        if not target_formula:
            return f"❌ 未找到ID为 {formula_id} 的公式"

        response = requests.delete(f"{API_BASE_URL}/admin/formulas/{formula_id}")
        if response.status_code == 200:
            latex_preview = target_formula['latex'][:30] + "..." if len(target_formula['latex']) > 30 else target_formula['latex']
            return f"✅ 公式删除成功\nID: {formula_id}\n内容: {latex_preview}"
        elif response.status_code == 404:
            return f"❌ 公式 {formula_id} 未找到"
        else:
            return f"❌ 删除公式时出错：{response.text}"
    except Exception as e:
        return f"❌ 删除公式时出错：{e}"


def delete_formula_with_refresh(formula_id: int) -> tuple:
    """删除公式并刷新表格"""
    try:
        result = delete_formula(formula_id)
        # 删除后刷新表格
        new_table = get_formulas()
        return result, new_table
    except Exception as e:
        return f"❌ 操作出错: {str(e)}", get_formulas()


def get_submission_image(submission_id: int):
    """获取提交的图片用于显示"""
    try:
        if not submission_id or submission_id <= 0:
            return None

        response = requests.get(f"{API_BASE_URL}/admin/submissions/{submission_id}")
        if response.status_code == 200:
            submission = response.json()
            image_path = submission.get('image_path')
            if image_path:
                print(f"尝试加载图片: {image_path}")

                # 路径尝试列表
                paths_to_try = [
                    image_path,  # 原始路径
                    os.path.join(os.path.dirname(os.path.dirname(__file__)), image_path),  # 相对于backend目录
                    os.path.join(os.getcwd(), image_path),  # 相对于当前工作目录
                    os.path.join(os.path.dirname(__file__), "..", image_path),  # 相对于ui目录的上级
                ]

                for path in paths_to_try:
                    if os.path.exists(path):
                        print(f"找到图片文件: {path}")
                        try:
                            img = Image.open(path)
                            # 确保图片格式正确
                            if img.mode not in ('RGB', 'RGBA'):
                                img = img.convert('RGB')
                            print(f"成功加载图片，尺寸: {img.size}")

                            # 根据图片尺寸调整显示大小，但保持合理的最大尺寸
                            width, height = img.size
                            max_width, max_height = 800, 600

                            # 如果图片太大，按比例缩放
                            if width > max_width or height > max_height:
                                ratio = min(max_width / width, max_height / height)
                                new_width = int(width * ratio)
                                new_height = int(height * ratio)
                                img = img.resize((new_width, new_height), Image.Resampling.LANCZOS)
                                print(f"图片已缩放至: {img.size}")

                            return img
                        except Exception as img_error:
                            print(f"打开图片失败 {path}: {img_error}")
                            continue

                print(f"所有路径都无法找到图片文件: {image_path}")
                return None
            else:
                print("提交记录中没有图片路径")
                return None
        else:
            print(f"获取提交记录失败: {response.status_code}")
            return None
    except Exception as e:
        print(f"Error fetching submission image: {e}")
        return None


def refresh_formulas():
    """Refresh the formulas table."""
    return get_formulas()


def refresh_submissions():
    """Refresh the submissions table."""
    return get_submissions()


def filter_submissions(formula_choice, status_choice):
    """根据筛选条件获取提交记录"""
    try:
        # 处理公式筛选
        formula_id = None
        if formula_choice and formula_choice != "全部公式":
            # 从选择中提取公式ID
            if isinstance(formula_choice, tuple):
                formula_id = formula_choice[1]
            else:
                # 如果是字符串，尝试解析ID
                try:
                    if formula_choice.startswith("ID"):
                        formula_id = int(formula_choice.split(":")[0].replace("ID", ""))
                except:
                    formula_id = None

        # 处理状态筛选
        status = None
        if status_choice and status_choice != "全部状态":
            # 状态映射：中文到英文
            status_map = {
                '待处理': 'pending',
                '处理中': 'processing',
                '已完成': 'completed',
                '失败': 'failed'
            }
            status = status_map.get(status_choice, status_choice)

        # 获取筛选后的数据
        filtered_data = get_submissions(formula_id=formula_id, status=status)

        # 生成统计信息
        stats_text = "筛选结果: "
        conditions = []
        if formula_choice and formula_choice != "全部公式":
            conditions.append(f"公式={formula_choice}")
        if status_choice and status_choice != "全部状态":
            conditions.append(f"状态={status_choice}")

        if conditions:
            stats_text += f"按 {', '.join(conditions)} 筛选，"
        else:
            stats_text += "显示所有记录，"

        stats_text += f"共 {len(filtered_data)} 条记录"

        return filtered_data, stats_text
    except Exception as e:
        print(f"筛选提交记录时出错: {e}")
        return get_submissions(), f"筛选出错: {str(e)}"


def refresh_formula_choices():
    """刷新公式选择列表"""
    return gr.Dropdown(choices=get_formula_choices(), value="全部公式")


def update_submission_status(submission_id: int, new_status: str, ocr_result: str = ""):
    """更新提交状态"""
    try:
        if not submission_id or submission_id <= 0:
            return "❌ 请输入有效的提交ID"

        # 验证状态值
        valid_statuses = ['pending', 'processing', 'completed', 'failed']
        if new_status not in valid_statuses:
            return f"❌ 无效的状态值。有效值: {', '.join(valid_statuses)}"

        update_data = {
            "status": new_status
        }
        if ocr_result.strip():
            update_data["ocr_result"] = ocr_result.strip()

        response = requests.put(
            f"{API_BASE_URL}/admin/submissions/{submission_id}",
            json=update_data
        )

        # 状态中文映射
        status_chinese = {
            'pending': '待处理',
            'processing': '处理中',
            'completed': '已完成',
            'failed': '失败'
        }

        if response.status_code == 200:
            return f"✅ 提交 {submission_id} 状态已更新为: {status_chinese.get(new_status, new_status)}"
        else:
            return f"❌ 更新失败: {response.text}"
    except Exception as e:
        return f"❌ 更新时出错: {str(e)}"


def update_status_with_button(submission_id: int, status: str, ocr_result: str = ""):
    """通过按钮更新状态的包装函数"""
    return update_submission_status(submission_id, status, ocr_result)


def get_all_submission_ids():
    """获取所有提交记录的ID列表"""
    try:
        response = requests.get(f"{API_BASE_URL}/admin/submissions", params={"limit": 1000})
        if response.status_code == 200:
            data = response.json()
            submissions = data.get('submissions', [])
            # 按ID排序，确保顺序一致
            ids = sorted([sub['id'] for sub in submissions])
            return ids
        else:
            return []
    except Exception as e:
        print(f"获取提交ID列表时出错: {e}")
        return []


def get_submission_id_range():
    """获取提交记录ID的有效范围"""
    try:
        all_ids = get_all_submission_ids()
        if all_ids:
            return min(all_ids), max(all_ids), len(all_ids)
        else:
            return 1, 1, 0
    except Exception as e:
        print(f"获取ID范围时出错: {e}")
        return 1, 1, 0


def get_id_range_info():
    """获取ID范围信息字符串"""
    try:
        min_id, max_id, total_count = get_submission_id_range()
        if total_count > 0:
            return f"有效ID范围: {min_id}-{max_id} (共{total_count}条记录)"
        else:
            return "暂无提交记录"
    except Exception as e:
        return f"获取范围信息出错: {str(e)}"


def navigate_submission(current_id: int, direction: str):
    """导航到上一张或下一张提交记录"""
    try:
        if not current_id or current_id <= 0:
            return current_id, "请先获取一个有效的提交记录", "", None, "位置信息不可用"

        all_ids = get_all_submission_ids()
        if not all_ids:
            return current_id, "没有找到提交记录", "", None, "没有提交记录"

        try:
            current_index = all_ids.index(current_id)
        except ValueError:
            # 如果当前ID不在列表中，返回第一个
            new_id = all_ids[0]
            details, current_status, current_ocr, image = get_submission_details(new_id)
            position_info = f"第 1 / {len(all_ids)} 张 (ID: {new_id})"
            return new_id, details, current_ocr, image, position_info

        if direction == "prev":
            # 上一张
            new_index = (current_index - 1) % len(all_ids)
        else:  # direction == "next"
            # 下一张
            new_index = (current_index + 1) % len(all_ids)

        new_id = all_ids[new_index]

        # 获取新的提交详情
        details, current_status, current_ocr, image = get_submission_details(new_id)

        # 生成位置信息
        position_info = f"第 {new_index + 1} / {len(all_ids)} 张 (ID: {new_id})"

        return new_id, details, current_ocr, image, position_info

    except Exception as e:
        print(f"导航提交记录时出错: {e}")
        return current_id, f"导航出错: {str(e)}", "", None, "导航出错"


def get_position_info(submission_id: int):
    """获取当前提交记录的位置信息"""
    try:
        if not submission_id or submission_id <= 0:
            return "请输入有效的提交ID"

        all_ids = get_all_submission_ids()
        if not all_ids:
            return "没有提交记录"

        try:
            current_index = all_ids.index(submission_id)
            return f"第 {current_index + 1} / {len(all_ids)} 张 (ID: {submission_id})"
        except ValueError:
            return f"ID {submission_id} 不在当前记录中"

    except Exception as e:
        return f"获取位置信息出错: {str(e)}"


def navigate_to_first():
    """导航到第一张提交记录"""
    try:
        all_ids = get_all_submission_ids()
        if not all_ids:
            return None, "没有提交记录", "", None, "没有提交记录"

        first_id = all_ids[0]
        details, current_status, current_ocr, image = get_submission_details(first_id)
        position_info = f"第 1 / {len(all_ids)} 张 (ID: {first_id})"

        return first_id, position_info, details, current_ocr, image
    except Exception as e:
        return None, "导航出错", f"导航出错: {str(e)}", "", None


def navigate_to_last():
    """导航到最后一张提交记录"""
    try:
        all_ids = get_all_submission_ids()
        if not all_ids:
            return None, "没有提交记录", "", None, "没有提交记录"

        last_id = all_ids[-1]
        details, current_status, current_ocr, image = get_submission_details(last_id)
        position_info = f"第 {len(all_ids)} / {len(all_ids)} 张 (ID: {last_id})"

        return last_id, position_info, details, current_ocr, image
    except Exception as e:
        return None, "导航出错", f"导航出错: {str(e)}", "", None


def get_submission_details(submission_id: int):
    """获取提交详情用于状态更新"""
    try:
        if not submission_id or submission_id <= 0:
            return "请输入有效的提交ID", "", "", None

        response = requests.get(f"{API_BASE_URL}/admin/submissions/{submission_id}")
        if response.status_code == 200:
            submission = response.json()
            current_status = submission.get('status', 'pending')
            current_ocr = submission.get('ocr_result', '')
            formula_info = f"公式: {submission.get('formula', {}).get('latex', '无')}"

            # 获取图片
            image = get_submission_image(submission_id)

            return formula_info, current_status, current_ocr or "", image
        else:
            return "获取提交信息失败", "", "", None
    except Exception as e:
        return f"错误: {str(e)}", "", "", None


# 创建Gradio界面
def create_admin_interface():
    with gr.Blocks(title="飞书公式抄写小程序 - 管理控制台", theme=gr.themes.Soft()) as demo:
        gr.Markdown("# 🧮 飞书公式抄写小程序 - 管理控制台")
        gr.Markdown("欢迎使用管理控制台，您可以在这里管理公式库、查看用户提交记录和统计数据。")

        with gr.Tabs():
            # 统计仪表板
            with gr.TabItem("📊 数据统计"):
                gr.Markdown("## 📈 系统概览")

                # 获取统计数据
                stats = get_statistics()

                with gr.Row():
                    with gr.Column():
                        gr.Markdown("### 📋 基础统计")
                        basic_stats_md = gr.Markdown(f"""
                        **公式总数：** {stats['formulas_count']} 个
                        **提交总数：** {stats['total_submissions']} 次
                        **今日提交：** {stats['today_submissions']} 次
                        """)

                    with gr.Column():
                        gr.Markdown("### 📊 状态分布")
                        status_stats_md = gr.Markdown("\n".join([
                            f"**{status}：** {count} 次"
                            for status, count in stats['status_counts'].items()
                        ]))

                refresh_stats_btn = gr.Button("🔄 刷新统计数据", variant="primary")

                # 图表区域
                gr.Markdown("## 📊 数据可视化")

                with gr.Row():
                    with gr.Column():
                        # 提交趋势图
                        try:
                            trend_chart = create_submission_trend_chart()
                            trend_plot = gr.Plot(
                                value=trend_chart,
                                label="提交趋势图"
                            )
                        except Exception as e:
                            print(f"创建趋势图时出错: {e}")
                            trend_plot = gr.Markdown("📈 趋势图暂时无法显示")

                    with gr.Column():
                        # 状态分布饼图
                        try:
                            status_chart = create_status_pie_chart()
                            status_plot = gr.Plot(
                                value=status_chart,
                                label="状态分布图"
                            )
                        except Exception as e:
                            print(f"创建状态图时出错: {e}")
                            status_plot = gr.Markdown("📊 状态图暂时无法显示")

                # 公式热度排行图
                try:
                    popularity_chart = create_formula_popularity_chart()
                    popularity_plot = gr.Plot(
                        value=popularity_chart,
                        label="公式热度排行"
                    )
                except Exception as e:
                    print(f"创建热度图时出错: {e}")
                    popularity_plot = gr.Markdown("🔥 热度图暂时无法显示")

            # 公式管理
            with gr.TabItem("📝 公式管理"):
                gr.Markdown("## 🔧 公式库管理")

                with gr.Row():
                    with gr.Column():
                        gr.Markdown("### ➕ 添加新公式")
                        latex_input = gr.Textbox(
                            label="LaTeX公式",
                            placeholder="请输入LaTeX公式 (例如: E = mc^2)",
                            lines=2
                        )
                        create_btn = gr.Button("✅ 创建公式", variant="primary")
                        create_result = gr.Textbox(label="操作结果", interactive=False)

                        gr.Markdown("### 🗑️ 快速删除")
                        with gr.Row():
                            delete_id_input = gr.Number(label="公式ID", precision=0, scale=2)
                            delete_btn = gr.Button("❌ 删除", variant="stop", scale=1)
                        delete_result = gr.Textbox(label="删除结果", interactive=False)

                    with gr.Column():
                        gr.Markdown("### 📋 公式列表 (点击操作列可删除)")
                        formulas_table = gr.Dataframe(
                            value=get_formulas(),
                            label="公式列表",
                            interactive=True,
                            wrap=True
                        )
                        with gr.Row():
                            refresh_formulas_btn = gr.Button("🔄 刷新列表", variant="secondary")
                            selected_info = gr.Textbox(label="选中信息", interactive=False, scale=2)

                # 表格选择处理
                def handle_table_select(evt: gr.SelectData):
                    """处理表格选择事件"""
                    try:
                        if evt.index[1] == 3:  # 操作列被点击
                            row_data = evt.value
                            # 获取当前表格数据
                            current_df = get_formulas()
                            if not current_df.empty and evt.index[0] < len(current_df):
                                formula_id = current_df.iloc[evt.index[0]]['ID']
                                latex_formula = current_df.iloc[evt.index[0]]['LaTeX公式']
                                return f"选中删除: ID {formula_id} - {latex_formula[:50]}...", formula_id
                        else:
                            # 其他列被点击，显示信息
                            current_df = get_formulas()
                            if not current_df.empty and evt.index[0] < len(current_df):
                                formula_id = current_df.iloc[evt.index[0]]['ID']
                                latex_formula = current_df.iloc[evt.index[0]]['LaTeX公式']
                                return f"查看: ID {formula_id} - {latex_formula}", formula_id
                        return "请点击操作列进行删除", None
                    except Exception as e:
                        return f"选择出错: {str(e)}", None

                # 事件处理
                create_btn.click(create_formula, inputs=[latex_input], outputs=[create_result])
                delete_btn.click(
                    delete_formula_with_refresh,
                    inputs=[delete_id_input],
                    outputs=[delete_result, formulas_table]
                )
                refresh_formulas_btn.click(refresh_formulas, outputs=[formulas_table])

                # 表格点击事件
                formulas_table.select(
                    handle_table_select,
                    outputs=[selected_info, delete_id_input]
                )

            # 提交记录管理
            with gr.TabItem("📷 提交管理"):
                gr.Markdown("## 👥 用户提交记录")

                # 筛选区域
                gr.Markdown("### 🔍 筛选条件")
                with gr.Row():
                    with gr.Column():
                        formula_filter = gr.Dropdown(
                            choices=get_formula_choices(),
                            label="按公式筛选",
                            value="全部公式",
                            interactive=True
                        )
                    with gr.Column():
                        status_filter = gr.Dropdown(
                            choices=["全部状态", "待处理", "处理中", "已完成", "失败"],
                            label="按状态筛选",
                            value="全部状态",
                            interactive=True
                        )
                    with gr.Column():
                        filter_btn = gr.Button("🔍 应用筛选", variant="primary")
                        clear_filter_btn = gr.Button("🗑️ 清除筛选", variant="secondary")

                # 筛选结果统计
                filter_stats = gr.Textbox(label="筛选结果", value="显示所有提交记录", interactive=False)

                # 提交记录列表
                gr.Markdown("### 📋 提交记录列表")
                submissions_table = gr.Dataframe(value=get_submissions(), label="提交记录")
                refresh_submissions_btn = gr.Button("🔄 刷新提交记录")

                # 状态更新区域
                gr.Markdown("### ⚙️ 状态管理")
                with gr.Row():
                    with gr.Column():
                        gr.Markdown("#### 📋 提交信息")

                        # ID范围信息
                        id_range_display = gr.Textbox(
                            label="ID范围信息",
                            value=get_id_range_info(),
                            interactive=False,
                            show_label=True
                        )

                        with gr.Row():
                            status_id_input = gr.Number(
                                label="提交ID",
                                precision=0,
                                scale=2,
                                info="请输入有效的提交记录ID"
                            )
                            get_details_btn = gr.Button("📋 获取详情", variant="secondary", scale=1)

                        # 导航按钮
                        with gr.Row():
                            prev_btn = gr.Button("⬅️ 上一张 (←)", variant="secondary", scale=1)
                            next_btn = gr.Button("➡️ 下一张 (→)", variant="secondary", scale=1)

                        # 快速导航
                        with gr.Row():
                            first_btn = gr.Button("⏮️ 第一张", variant="secondary", size="sm", scale=1)
                            last_btn = gr.Button("⏭️ 最后一张", variant="secondary", size="sm", scale=1)

                        # 位置信息
                        position_info = gr.Textbox(label="位置信息", value="请先获取提交记录", interactive=False)
                        submission_details = gr.Textbox(label="提交详情", interactive=False)

                    with gr.Column():
                        gr.Markdown("#### 🖼️ 提交图片")
                        status_submission_image = gr.Image(
                            label="用户提交的图片",
                            show_label=True,
                            show_download_button=True,
                            interactive=False,
                            container=True,
                            show_share_button=False
                        )

                with gr.Row():
                    with gr.Column():
                        gr.Markdown("#### 🔄 状态操作")
                        with gr.Row():
                            pending_btn = gr.Button("⏳ 待处理", variant="secondary")
                            processing_btn = gr.Button("🔄 处理中", variant="secondary")
                        with gr.Row():
                            completed_btn = gr.Button("✅ 已完成", variant="primary")
                            failed_btn = gr.Button("❌ 失败", variant="stop")

                    with gr.Column():
                        gr.Markdown("#### 📝 OCR结果")
                        ocr_result_input = gr.Textbox(label="OCR结果（可选）", placeholder="输入OCR识别结果...")

                status_update_result = gr.Textbox(label="操作结果", interactive=False)

                # 筛选和刷新事件处理
                def clear_filters():
                    """清除所有筛选条件"""
                    return "全部公式", "全部状态", get_submissions(), "显示所有提交记录"

                # 事件处理
                refresh_submissions_btn.click(refresh_submissions, outputs=[submissions_table])
                filter_btn.click(
                    filter_submissions,
                    inputs=[formula_filter, status_filter],
                    outputs=[submissions_table, filter_stats]
                )
                clear_filter_btn.click(
                    clear_filters,
                    outputs=[formula_filter, status_filter, submissions_table, filter_stats]
                )


                # 获取详情事件（包含图片）
                def get_details_wrapper(submission_id):
                    """获取详情的包装函数"""
                    details, current_status, current_ocr, image = get_submission_details(submission_id)
                    pos_info = get_position_info(submission_id)
                    range_info = get_id_range_info()  # 刷新ID范围信息
                    return range_info, pos_info, details, current_ocr, image

                get_details_btn.click(
                    get_details_wrapper,
                    inputs=[status_id_input],
                    outputs=[id_range_display, position_info, submission_details, ocr_result_input, status_submission_image]
                )

                # 导航按钮事件
                def navigate_prev(current_id):
                    """导航到上一张"""
                    new_id, details, ocr, image, pos_info = navigate_submission(current_id, "prev")
                    range_info = get_id_range_info()
                    return range_info, new_id, pos_info, details, ocr, image

                def navigate_next(current_id):
                    """导航到下一张"""
                    new_id, details, ocr, image, pos_info = navigate_submission(current_id, "next")
                    range_info = get_id_range_info()
                    return range_info, new_id, pos_info, details, ocr, image

                prev_btn.click(
                    navigate_prev,
                    inputs=[status_id_input],
                    outputs=[id_range_display, status_id_input, position_info, submission_details, ocr_result_input, status_submission_image]
                )

                next_btn.click(
                    navigate_next,
                    inputs=[status_id_input],
                    outputs=[id_range_display, status_id_input, position_info, submission_details, ocr_result_input, status_submission_image]
                )

                # 快速导航按钮事件
                def navigate_first_with_range():
                    """导航到第一张并更新范围信息"""
                    first_id, pos_info, details, ocr, image = navigate_to_first()
                    range_info = get_id_range_info()
                    return range_info, first_id, pos_info, details, ocr, image

                def navigate_last_with_range():
                    """导航到最后一张并更新范围信息"""
                    last_id, pos_info, details, ocr, image = navigate_to_last()
                    range_info = get_id_range_info()
                    return range_info, last_id, pos_info, details, ocr, image

                first_btn.click(
                    navigate_first_with_range,
                    outputs=[id_range_display, status_id_input, position_info, submission_details, ocr_result_input, status_submission_image]
                )

                last_btn.click(
                    navigate_last_with_range,
                    outputs=[id_range_display, status_id_input, position_info, submission_details, ocr_result_input, status_submission_image]
                )

                # 状态按钮事件
                pending_btn.click(
                    lambda id, ocr: update_status_with_button(id, "pending", ocr),
                    inputs=[status_id_input, ocr_result_input],
                    outputs=[status_update_result]
                )
                processing_btn.click(
                    lambda id, ocr: update_status_with_button(id, "processing", ocr),
                    inputs=[status_id_input, ocr_result_input],
                    outputs=[status_update_result]
                )
                completed_btn.click(
                    lambda id, ocr: update_status_with_button(id, "completed", ocr),
                    inputs=[status_id_input, ocr_result_input],
                    outputs=[status_update_result]
                )
                failed_btn.click(
                    lambda id, ocr: update_status_with_button(id, "failed", ocr),
                    inputs=[status_id_input, ocr_result_input],
                    outputs=[status_update_result]
                )

                # 统计数据刷新事件
                def refresh_all_stats():
                    try:
                        stats = get_statistics()
                        basic_stats_text = f"""
                        **公式总数：** {stats['formulas_count']} 个
                        **提交总数：** {stats['total_submissions']} 次
                        **今日提交：** {stats['today_submissions']} 次
                        """
                        status_stats_text = "\n".join([
                            f"**{status}：** {count} 次"
                            for status, count in stats['status_counts'].items()
                        ])

                        # 安全地创建图表
                        try:
                            trend_chart = create_submission_trend_chart()
                        except Exception as e:
                            print(f"刷新趋势图时出错: {e}")
                            trend_chart = None

                        try:
                            status_chart = create_status_pie_chart()
                        except Exception as e:
                            print(f"刷新状态图时出错: {e}")
                            status_chart = None

                        try:
                            popularity_chart = create_formula_popularity_chart()
                        except Exception as e:
                            print(f"刷新热度图时出错: {e}")
                            popularity_chart = None

                        return (
                            basic_stats_text,
                            status_stats_text,
                            trend_chart,
                            status_chart,
                            popularity_chart
                        )
                    except Exception as e:
                        print(f"刷新统计数据时出错: {e}")
                        return (
                            "❌ 数据加载失败",
                            "❌ 数据加载失败",
                            None,
                            None,
                            None
                        )

                # 只有当图表组件成功创建时才绑定刷新事件
                try:
                    refresh_stats_btn.click(
                        refresh_all_stats,
                        outputs=[
                            basic_stats_md,
                            status_stats_md,
                            trend_plot,
                            status_plot,
                            popularity_plot
                        ]
                    )
                except Exception as e:
                    print(f"绑定刷新事件时出错: {e}")
                    # 如果图表组件创建失败，只刷新文本统计
                    def refresh_text_stats():
                        try:
                            stats = get_statistics()
                            basic_stats_text = f"""
                            **公式总数：** {stats['formulas_count']} 个
                            **提交总数：** {stats['total_submissions']} 次
                            **今日提交：** {stats['today_submissions']} 次
                            """
                            status_stats_text = "\n".join([
                                f"**{status}：** {count} 次"
                                for status, count in stats['status_counts'].items()
                            ])
                            return basic_stats_text, status_stats_text
                        except Exception as e:
                            print(f"刷新文本统计时出错: {e}")
                            return "❌ 数据加载失败", "❌ 数据加载失败"

                    refresh_stats_btn.click(
                        refresh_text_stats,
                        outputs=[basic_stats_md, status_stats_md]
                    )

    return demo


def launch_admin_ui(port: int = 7860, host: str = "0.0.0.0"):
    """启动管理界面"""
    print(f"正在启动Gradio管理界面...")
    print(f"API基础URL: {API_BASE_URL}")

    # 测试API连接
    if test_api_connection():
        print("✅ API连接测试成功")
    else:
        print("❌ API连接测试失败，请检查后端服务是否正常运行")

    demo = create_admin_interface()
    demo.launch(
        server_name=host,
        server_port=port,
        share=False,
        show_error=True
    )


if __name__ == "__main__":
    launch_admin_ui()
